#ifndef S2E_PLUGINS_COMMANDLINEPARSER_H
#define S2E_PLUGINS_COMMANDLINEPARSER_H

#include <s2e/cpu.h>
#include <s2e/opcodes.h>

#include <s2e/CorePlugin.h>
#include <s2e/Plugin.h>
#include <s2e/S2EExecutionState.h>
#include <s2e/Utils.h>
#include <s2e/Plugins/Core/BaseInstructions.h>
#include <s2e/S2EExecutionState.h>
#include <s2e/Plugins/OSMonitors/OSMonitor.h>
#include <s2e/Plugins/OSMonitors/Linux/LinuxMonitor.h>
#include <s2e/Plugins/OSMonitors/Support/ModuleExecutionDetector.h>
#include <s2e/Plugins/OSMonitors/Support/ProcessExecutionDetector.h>
namespace s2e {
namespace plugins {
namespace python {
class PythonS2E: public Plugin {
S2E_PLUGIN

private:
	OSMonitor *m_monitor;
	ProcessExecutionDetector *m_process;
	sigc::connection m_ins_connection_before;
	sigc::connection m_ins_connection_after;

	std::string m_python_so_file;
	std::string m_script_file;
	ModuleExecutionDetector *m_detector;

	void onModuleTranslateBlockStart(ExecutionSignal *signal,
			S2EExecutionState *state, const ModuleDescriptor &module,
			TranslationBlock *tb, uint64_t pc);
	void onTranslateInstructionStart(ExecutionSignal *signal,
			S2EExecutionState *state, TranslationBlock *tb, uint64_t pc,
			uint64_t addend);
	void onTranslateInstructionEnd(ExecutionSignal *signal,
			S2EExecutionState *state, TranslationBlock *tb, uint64_t pc,
			uint64_t addend);
	void beforeExecuteInstruction(S2EExecutionState *state, uint64_t pc);
	void afterExecuteInstruction(S2EExecutionState *state, uint64_t pc);

	void onTranslateSpecialInstructionEnd(ExecutionSignal *signal,
			S2EExecutionState *state, TranslationBlock *tb, uint64_t pc,
			enum special_instruction_t type);
	void onTranslateSoftInterruptStart(ExecutionSignal *signal,
			S2EExecutionState *state, TranslationBlock *tb, uint64_t pc,
			unsigned vector);

	void onSyscallInst(S2EExecutionState *state, uint64_t pc);
	void onSyscallInt(S2EExecutionState *state, uint64_t pc);
	void processSyscallEntry(S2EExecutionState *state, uint64_t pc,
			target_ulong syscallid);

	void onEveryTranslateInstructionStart(ExecutionSignal *signal,
			S2EExecutionState *state, TranslationBlock *tb, uint64_t pc);
	void onEveryExecInstruction(S2EExecutionState *state, uint64_t pc);
	std::map<uint64_t /*tid*/, uint64_t /*pc*/> m_sysCallRecord;
public:
	PythonS2E(S2E *s2e) :
			Plugin(s2e) {
	}
	~PythonS2E();
	void initialize(void);
	bool execScript(const char *fileName);
	int fopen_s(FILE **fd, const char *fn, const char *flags);

};

}
}
}

#endif
